﻿//----------------------------------------------------------------------------
// Copyright (c) Pavel Tishkin 2012-2013.
//
// You must not remove this notice, or any other, from this software.
//----------------------------------------------------------------------------


[<AutoOpenAttribute>]
module Prelude

open System.Runtime.CompilerServices


let inline _toValue _ x     = x

let inline _toConst c _     = c


/// Pretty print any object
let inline ppp x = printfn "%A" x

let inline spp x = sprintf "%A" x



type System.String with   
    member inline e.to_s()                      = match e with null -> "" | _ -> e
    member inline e.format([<System.ParamArray>] xs : obj[]) = System.String.Format(e, xs)

    /// True if sequence has `this` string
    member inline e.isInSeq (xs: string seq)    = Seq.exists ((=)e) xs

    /// Safe `left` function for string
    member inline e.left (cnt : int)            = if e.Length > cnt then e.[0..cnt - 1] else e
    member inline e.left_ellipses (cnt : int)   = if e.Length > cnt then e.[0..cnt - 1] + "..." else e

    //[<ExtensionAttribute>]
    //member inline e.format(xs : obj) = System.String.Format(e, xs)


type System.Object with   
    member inline e.to_s()    = 
        match e with
        | null -> ""
        | :? System.DBNull                          -> ""
        | :? System.Data.SqlTypes.INullable as iNull when iNull.IsNull -> ""
        | :? double as e                            -> e.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat)
        | :? decimal as e                           -> e.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat)
        | :? System.Data.SqlTypes.SqlDecimal as e   -> e.Value.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat)
        | :? System.Data.SqlTypes.SqlDouble  as e   -> e.Value.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat)
        | :? System.DateTime as e                   -> e.ToString("yyyy-MM-dd HH:mm:ss")
        | :? System.Data.SqlTypes.SqlDateTime as e  -> e.Value.ToString("yyyy-MM-dd HH:mm:ss")
        | _ -> System.String.Format("{0}", e)














[<Extension>]
type AnyTypeExtension = 

    [<Extension>] 
    static member inline isNone(e : ^A) = 
        match box e with
        | null                  -> true
        | :? string as x        -> System.String.IsNullOrEmpty x
        | :? System.DBNull      -> true
        | :? System.Data.SqlTypes.INullable as iNull  -> iNull.IsNull
        | _                     -> System.Object.ReferenceEquals(e, null)

    [<Extension>] 
    static member inline isSome(x : ^A)                     = AnyTypeExtension.isNone(x) |> not






let inline isNone (e : ^A)      = AnyTypeExtension.isNone(e)
let inline isSome (e : ^A)      = AnyTypeExtension.isSome(e)
let inline noneTo defv (e : ^A) = if AnyTypeExtension.isNone e then defv else e

let inline to_s e               = 
    match box e with
    | null -> ""
    #if UNIONS2S
    | _ ->
    let typ = e.GetType()
    if Microsoft.FSharp.Reflection.FSharpType.IsUnion typ then
        match typ.BaseType with
        | null                           -> sprintf "%s%s" typ.Name (sprintf "%A" e)
        | n when n.Name = "HtmlTagEntry" -> e.to_s()
        | _                              -> sprintf "%s%s" typ.Name (sprintf "%A" e)
    else e.to_s()
    #else
    | _ -> e.to_s()
    #endif

type System.String with   
    member inline x.join(xs : ^A seq) = String.concat x (Seq.map to_s xs)






type System.Nullable<'a when 'a : struct
                        and  'a : (new : unit -> 'a)
                        and  'a :> System.ValueType> with

    member x.AsOption() =
        match x.HasValue with
        | true  -> Some(x.Value)
        | false -> None











